package com.zhangzhan.service.impl;

import com.sun.org.apache.bcel.internal.generic.L2D;
import com.zhangzhan.domain.commcon.ResponseResult;
import com.zhangzhan.domain.entity.LoginUser;
import com.zhangzhan.domain.entity.Menu;
import com.zhangzhan.domain.entity.User;
import com.zhangzhan.domain.vo.AdminUserInfoVo;
import com.zhangzhan.domain.vo.MenuVO;
import com.zhangzhan.domain.vo.UserInfoVo;
import com.zhangzhan.mapper.MenuMapper;
import com.zhangzhan.service.LoginService;
import com.zhangzhan.service.MenuService;
import com.zhangzhan.service.RoleService;
import com.zhangzhan.utils.BeanCopyUtils;
import com.zhangzhan.utils.JwtUtil;
import com.zhangzhan.utils.RedisCache;
import com.zhangzhan.utils.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class SystemLoginServiceImpl implements LoginService {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private MenuService menuService;
    @Autowired
    private MenuMapper menuMapper;

    @Autowired
    private RoleService roleService;

    @Override
    public ResponseResult login(User user) {
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(user.getUserName(),user.getPassword());
        Authentication authenticate = authenticationManager.authenticate(authenticationToken);
        //判断是否认证通过
        if(Objects.isNull(authenticate)){
            throw new RuntimeException("用户名或密码错误");
        }
        //获取userid 生成token
        LoginUser loginUser = (LoginUser) authenticate.getPrincipal();
        String userId = loginUser.getUser().getId().toString();
        String jwt = JwtUtil.createJWT(userId);
        //把用户信息存入redis
        redisCache.setCacheObject("login:"+userId,loginUser);

        //把token封装 返回
		Map<String,String> map = new HashMap<>();
        map.put("token",jwt);
        return ResponseResult.okResult(map);
    }

    /**
     * @description 用户权限查询
     *
     * @return com.zhangzhan.domain.commcon.ResponseResult<com.zhangzhan.domain.vo.AdminUserInfoVo>
     * @author 31115
     * @date 2022/12/5 15:01
     */
    @Override
    public ResponseResult<AdminUserInfoVo> getInfo() {
        //获取当前用户信息
        LoginUser loginUser = SecurityUtils.getLoginUser();
        //查询当前用户的权限信息
        List<String>  permissions = menuService.selectPermsByUserId(loginUser.getUser().getId());
        //查询当先用户是什么角色
        List<String> roles = roleService.selectRoleKeyByUserId(loginUser.getUser().getId());
        //封装vo并返回
        UserInfoVo userInfoVo = BeanCopyUtils.beanCopyUtils(loginUser.getUser(), UserInfoVo.class);
        AdminUserInfoVo vo = new AdminUserInfoVo();
        vo.setPermissions(permissions);
        vo.setRoles(roles);
        vo.setUser(userInfoVo);

        return ResponseResult.okResult(vo);
    }

    /**
     * @description 动态路由
     * @param userId
     * @return java.util.List<com.zhangzhan.domain.vo.MenuVO>
     * @author 31115
     * @date 2022/12/6 11:09
     */
    @Override
    public List<MenuVO> getRouters(Long userId) {
        //admin的用户可以访问所有模块
        List<MenuVO> menus = null;
        if (SecurityUtils.isAdmin()){
            //查询所有menu
          menus =  menuMapper.selectAdminMenu();
        }else {
            //如果是其他用户则根据id查对应的权限
          menus =  menuMapper.selectMenuById(userId);
        }

        //构建tree
        //先找出第一层的菜单  然后去找他们的子菜单设置到children属性中
        List<MenuVO> menuTree = builderMenuTree(menus,0L);
        return menuTree;
    }

    /**
     * @description 退出登录接口
     *
     * @return com.zhangzhan.domain.commcon.ResponseResult
     * @author 31115
     * @date 2022/12/6 14:17
     */
    @Override
    public ResponseResult logout() {
        //获取当前用户id
        Long userId = SecurityUtils.getUserId();

        //删除redis中的token
        redisCache.deleteObject("login:"+userId);
        return null;
    }

    /**
     * @description 封装根目录
     * @param menus
     * @param parentId
     * @return java.util.List<com.zhangzhan.domain.vo.MenuVO>
     * @author 31115
     * @date 2022/12/6 11:39
     */
    private List<MenuVO> builderMenuTree(List<MenuVO> menus, Long parentId) {
        List<MenuVO> menuTreeList = menus.stream()
                .filter(menu -> menu.getParentId().equals(parentId))
//                .map(menu -> menu.setChildren(getChinldren(menu, menus)))
                .map(new Function<MenuVO, MenuVO>() {
                    @Override
                    public MenuVO apply(MenuVO menuVO) {
                        return menuVO.setChildren(getChinldren(menuVO,menus));
                    }
                })
                .collect(Collectors.toList());

        return menuTreeList;
    }

    /**
     * @description 查询根目录的子标签 ，（递归）
     * @param menu
     * @param menus
     * @return java.util.List<com.zhangzhan.domain.vo.MenuVO>
     * @author 31115
     * @date 2022/12/6 11:39
     */
    private List<MenuVO> getChinldren(MenuVO menu, List<MenuVO> menus) {
        List<MenuVO> childrenList = menus.stream()
                .filter(m -> m.getParentId().equals(menu.getId()))
                .map(m -> m.setChildren(getChinldren(m, menus)))
                .collect(Collectors.toList());
        return childrenList;
    }
}